﻿/*
 * 对象缓存
 * 完全公开
 * Created By WangZg
 */
using System;
using System.Collections.Generic;
using System.Text;

namespace Octopus.Logging.Commons
{
    public class ObjectCache<T> where T : class
    {
        /// <summary>保存对象</summary>
        IDictionary<string, T> _store;
        /// <summary>保存对象的时间</summary>
        IDictionary<string, DateTime> _timer;
        /// <summary>更新方法的签名格式</summary>
        delegate void RefreshDelegate();
        /// <summary>更新缓存的方法</summary>
        RefreshDelegate RefreshFunction;
        /// <summary>更新缓存的时间</summary>
        int _RefreshSecond;

        /// <summary>创建同类对象的缓存</summary>
        /// <param name="nSecond">缓存更新时间</param>
        /// <param name="strategy">缓存更新策略(TimeSpan暂不支持，仅提供更新操作时刷新)</param>
        public ObjectCache(int nSecond, RefreshStrategy strategy)
        {
            _store = new Dictionary<string, T>();
            _timer = new Dictionary<string, DateTime>();

            _RefreshSecond = nSecond;
            if (strategy == RefreshStrategy.OnOperate)
            {                
                RefreshFunction = RefreshCacheByOP;
            }
            else
            {
                RefreshFunction = RefreshCacheByNever;
            }
        }

        public void Add(string key, T value)
        {
            lock (_store)
            {
                RefreshFunction();

                if (!_store.ContainsKey(key))
                {
                    _store.Add(key, value);
                    _timer.Add(key, DateTime.Now);
                }
            }
        }

        public void Remove(string key)
        {
            lock (_store)
            {
                RefreshFunction();

                if (_store.ContainsKey(key))
                {
                    _store.Remove(key);
                    _timer.Remove(key);
                }
            }
        }

        public void Update(string key, T value)
        {
            lock (_store)
            {
                RefreshFunction();

                if (_store.ContainsKey(key))
                {
                    _store[key] = value;
                    _timer[key] = DateTime.Now;
                }
                else
                {
                    _store.Add(key, value);
                    _timer.Add(key, DateTime.Now);
                }
            }
        }

        public T Get(string key)
        {
            lock (_store)
            {
                if (_store.ContainsKey(key))
                {
                    _timer[key] = DateTime.Now;
                    return _store[key];
                }
                return null;
            }
        }

        private void RefreshCacheByNever()
        {
        }
        private void RefreshCacheByOP()
        {
            IList<string> Keys = new List<string>(0);
            foreach (KeyValuePair<string, DateTime> p in _timer)
            {
                if (p.Value.AddSeconds(_RefreshSecond) < DateTime.Now)
                {
                    Keys.Add(p.Key);
                }
            }
            if (Keys.Count > 0) { RemoveDictionary(Keys); }
        }
        private void RemoveDictionary(IList<string> Keys)
        {
            foreach (string key in Keys)
            {
                _store.Remove(key);
                _timer.Remove(key);
            }
        }
    }

    /// <summary>刷新缓存过期数据的策略</summary>
    public enum RefreshStrategy
    {
        /// <summary>不刷新</summary>
        Never,
        /// <summary>增删改操作时刷新</summary>
        OnOperate,
        /// <summary>定时自动刷新</summary>
        TimeSpan,
    }
}

